home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume10 / dev.fd < prev    next >
Encoding:
Internet Message Format  |  1987-08-06  |  18.9 KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i098:  A /dev/fd device driver for 4.3 and NFS systems
  5. Message-ID: <790@uunet.UU.NET>
  6. Date: 7 Aug 87 11:24:25 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 660
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: emory!arnold (Arnold D. Robbins {EUCC})
  12. Posting-number: Volume 10, Issue 98
  13. Archive-name: dev.fd
  14.  
  15. [  The code here implements /dev/fd/0, /dev/fd/12, etc., so that a program
  16.    can treat its file descriptors as files; the README-FIRST describes
  17.    some possible tricks that one can now play with, e.g., KSH, as a result
  18.    of this.  --r$  ]
  19.  
  20. #! /bin/sh
  21. # This is a shell archive, meaning:
  22. # 1. Remove everything above the #! /bin/sh line.
  23. # 2. Save the resulting text in a file.
  24. # 3. Execute the file with /bin/sh (not csh) to create the files:
  25. #    README-FIRST
  26. #    README
  27. #    fd.4
  28. #    dev_fd.c
  29. #    PATCH
  30. export PATH; PATH=/bin:$PATH
  31. echo shar: extracting "'README-FIRST'" '(2045 characters)'
  32. if test -f 'README-FIRST'
  33. then
  34.     echo shar: will not over-write existing file "'README-FIRST'"
  35. else
  36. cat << \SHAR_EOF > 'README-FIRST'
  37. README-FIRST
  38.  
  39.     The files in this directory contain the source code for the "fd"
  40. pseudo-device driver for 4.[23] BSD Unix. The idea originated with the Eighth
  41. Edition Research Unix system.
  42.     The original version for BSD Unix was done by Fred Blonder at the
  43. University of Maryland. He simply had a bunch of devices, /dev/fd0 - /dev/fd19.
  44. The Research Unix system uses a /dev/fd directory, with files 0 - 19.
  45.     The latter version of the mechanism is used by the Korn shell (ksh)
  46. for "process substitution", a feature whereby programs can read/write files
  47. which are really pipes from/to other processes.  This mechanism allows one
  48. to have pipelines that move data in more than one dimension. Once this
  49. driver is installed, the ksh needs to be recompiled. Process substitution
  50. is new in the version of the ksh known as "ksh-i". I don't know if the older
  51. ksh had it as an undocumented feature.
  52.     To allow the ksh to use the fd driver, and for compatibility with
  53. Research Unix, I have changed the fd.4 man page to refer to the /dev/fd
  54. directory.
  55.  
  56.     This version of the fd driver now includes code for NFS systems.
  57. Unfortunately, for reasons detailed in the source code, the NFS version
  58. requires a small patch to the stock system code. The file that is affected
  59. is /sys/specfs/spec_vnodeops.c.  This patch is included in the file PATCH.
  60. This patch should not affect any other system code (famous last words!).
  61. Besides the NFS version, I have added some additional error checking, and
  62. a bug fix to the inode version as well. This is commented, so if someone
  63. wants the exact original code, they can change it back.
  64.  
  65.     The NFS version works without change on both Sun systems running
  66. SunOS 3.3, and Mt. Xinu 4.3 + NFS 3.2. On the Sun, "make depend" will not
  67. work because of where the inode.h file is included from if NFS is not
  68. defined. This is not a very big deal, just comment out that line.  The
  69. interaction with the file locking mechanisms is not clear. (i.e. I didn't
  70. bother to investigate it.)
  71.  
  72. Arnold Robbins
  73. Emory University Computing Center
  74. July, 1987
  75. SHAR_EOF
  76. chmod +x 'README-FIRST'
  77. fi # end of overwriting check
  78. echo shar: extracting "'README'" '(1781 characters)'
  79. if test -f 'README'
  80. then
  81.     echo shar: will not over-write existing file "'README'"
  82. else
  83. cat << \SHAR_EOF > 'README'
  84. From fred@gymble.UUCP (Fred Blonder) Fri Jun 21 00:34:53 1985
  85. Relay-Version: version B 2.10.2 9/18/84; site gatech.CSNET
  86. Posting-Version: version B 2.10.1 6/24/83; site gymble.UUCP
  87. Path: gatech!akgua!whuxlm!whuxl!houxm!ihnp4!mhuxn!mhuxr!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!umcp-cs!gymble!fred
  88. From: fred@gymble.UUCP (Fred Blonder)
  89. Newsgroups: net.sources
  90. Subject: ``file descriptor'' pseudo-device driver for 4.2BSD
  91. Message-ID: <173@gymble.UUCP>
  92. Date: 21 Jun 85 04:34:53 GMT
  93. Date-Received: 23 Jun 85 03:29:53 GMT
  94. Distribution: net
  95. Organization: U of Maryland, Laboratory for Parallel Computation, C.P., MD
  96. Lines: 272
  97.  
  98. I'm re-posting this due to popular demand:
  99.  
  100. This is a pseudo-device driver which implements a
  101. series of devices: /dev/fd0 - /dev/fd19 which are
  102. surreptitiously equivalenced to whatever file (if
  103. any) is associated with the corresponding file
  104. descriptor in the process which is attempting to
  105. open that file. In other words: opening the file
  106. /dev/fd<n> is almost the same as doing the system
  107. call: dup(n). It's different in that if the file
  108. is a device, the driver's open routine is called.
  109. If the corresponding file descriptor is a pipe
  110. (socket) a dup() sys call is faked.
  111.  
  112. This can be used to force programs to read from
  113. their standard input, or write to their standard
  114. output, even if they haven't been designed to do
  115. so.  For instance:
  116.  
  117.     ln -s /dev/fd0 xx.c
  118.     cc xx.c
  119.     { Type a C program here. }
  120.     ^D
  121.     a.out
  122.  
  123. Or, to see if a certain source file compiled into a
  124. particular object file:
  125.  
  126.     cc source.c -o /dev/fd1 | cmp - objectfile
  127.  
  128. Be sure to make these mods in your conf directory.
  129.  
  130. In the config file:
  131.     pseudo-device    fd
  132.  
  133. In the ``files'' file:
  134.     sys/dev_fd.c        optional fd
  135.  
  136. <**************************************************************>
  137. SHAR_EOF
  138. chmod +x 'README'
  139. fi # end of overwriting check
  140. echo shar: extracting "'fd.4'" '(3615 characters)'
  141. if test -f 'fd.4'
  142. then
  143.     echo shar: will not over-write existing file "'fd.4'"
  144. else
  145. cat << \SHAR_EOF > 'fd.4'
  146. ...
  147. ... $Header: fd.4,v 1.3 87/07/10 10:20:26 root Locked $
  148. ... 
  149. ... $Log:    fd.4,v $
  150. ... Revision 1.3  87/07/10  10:20:26  root
  151. ... Added ERRORS section. ADR.
  152. ... 
  153. ... Revision 1.2  87/07/05  12:05:49  root
  154. ... Added synopsis entry, changed for /dev/fd as a directory, added notes
  155. ... about ksh, /dev/std{in, out, err} and only having 20 entries. ADR.
  156. ... 
  157. ... Revision 1.1  87/07/02  15:28:01  root
  158. ... Initial revision
  159. ... 
  160. ...
  161. .TH FD 4 EUCC
  162. .UC 4
  163. .SH NAME
  164. /dev/fd/* \- ``file descriptor'' driver
  165. .SH SYNOPSIS
  166. .B "pseudo-device    fd"
  167. .SH DESCRIPTION
  168. .B /dev/fd/0
  169. -
  170. .B /dev/fd/19
  171. are special files that reference the files associated with a process'
  172. open file descriptors.
  173. That is, opening the file: \fB/dev/fd/\fIN\fR is equivalent to opening whatever
  174. file you opened to get the file descriptor
  175. .IR N ,
  176. even though you may not
  177. know the file's true name (or even if it has one).
  178. This can be used to force a program which opens files by name, to connect
  179. itself to open file descriptors (which you have thoughtfully provided) in
  180. weird and wonderful ways. A simple use would be to force a program which
  181. only accepts input from files, to read from its standard input.
  182. For instance:
  183. .sp
  184. .ti +10
  185. cat /dev/fd/0
  186. .sp
  187. produces the same result as:
  188. .sp
  189. .ti +10
  190. cat -
  191. .sp
  192. which would be useful if
  193. .IR cat (1)
  194. didn't use the ``-'' convention.
  195. .PP
  196. This driver is particularly useful for enabling the ``process substitution''
  197. mechanism in
  198. .IR ksh (1).
  199. .PP
  200. If the open file descriptor references a socket, the driver fakes a
  201. .IR dup (2)
  202. system call instead of actually opening a file. In this case it
  203. checks to see that the read/write mode you are attempting to open
  204. the file with, is compatible with the mode of the existing file descriptor.
  205. That is, if descriptor 5 refers to a socket and
  206. is open for writing, you cannot open
  207. .B /dev/fd/5
  208. for reading.
  209. .PP
  210. As a notational convenience, the files
  211. .BR /dev/stdin ,
  212. .BR /dev/stdout ,
  213. and
  214. .B /dev/stderr
  215. are provided as hard links to
  216. .BR /dev/fd/0 ,
  217. .BR /dev/fd/1 ,
  218. and
  219. .BR /dev/fd/2
  220. respectively.
  221. .SH ERRORS
  222. The named file descriptor will be ``opened'' as described above unless
  223. one of the following is true.
  224. .PP
  225. .TP 15
  226. [ENXIO]
  227. The file descriptor attempting to be reopened is larger than the
  228. maximum number of open files that a process may have.
  229. (E.g., attempting to open file descriptor 65 on a 4.3BSD system.)
  230. .TP 15
  231. [EBADF]
  232. The file descriptor attempting to be reopened is not an open file.
  233. .PP
  234. Other errors as would be returned by
  235. .IR access (2),
  236. and
  237. .IR open (2).
  238. .SH SEE ALSO
  239. .IR ksh (1),
  240. .IR access (2),
  241. .IR dup (2),
  242. .IR open (2).
  243. .SH AUTHOR
  244. Fred Blonder <Fred@mimsy.umd.EDU>
  245. .br
  246. NFS version by Arnold Robbins <arnold@emory.EDU>
  247. .SH FILES
  248. .BR /dev/fd/* ,
  249. .BR /dev/stdin ,
  250. .BR /dev/stdout ,
  251. .B /dev/stderr
  252. .SH BUGS
  253. Since, for sockets,
  254. the driver fakes a
  255. .I dup
  256. system call rather than actually re-opening
  257. the file, the new descriptor is a copy of the
  258. .IR dup 'ed
  259. descriptor, and shares
  260. its properties. Specifically: it will have the same read/write mode as the
  261. .IR dup 'ed
  262. descriptor. If descriptor 0 is open for reading and writing, opening
  263. .B /dev/fd/0
  264. for reading will return a writable, as well as readable, file
  265. descriptor.
  266. Also: the descriptors share the same read/write pointer, so seeks, reads and
  267. writes on one will affect the other.
  268. .PP
  269. While not a bug in the driver specifically, use of these files can produce odd
  270. interactions with programs which don't expect to have their file
  271. descriptors surreptitiously aliased.
  272. .PP
  273. Having only 20 entries in the
  274. .B /dev/fd
  275. directory is an anachronism; modern Unix systems allow
  276. a process to have many more open file descriptors.
  277. SHAR_EOF
  278. chmod +x 'fd.4'
  279. fi # end of overwriting check
  280. echo shar: extracting "'dev_fd.c'" '(8981 characters)'
  281. if test -f 'dev_fd.c'
  282. then
  283.     echo shar: will not over-write existing file "'dev_fd.c'"
  284. else
  285. cat << \SHAR_EOF > 'dev_fd.c'
  286. #ifndef lint
  287. static char rcsid[] = "@(#)$Header: dev_fd.c,v 1.6 87/07/10 10:24:13 root Locked $";
  288. #endif lint
  289.  
  290. /*
  291.  * fd.c        Fred Blonder - U of Maryland    11-Sep-1984
  292.  *
  293.  * ``File Descriptor'' pseudo-device driver, rewritten for Berkeley 4.2.
  294.  *
  295.  * Opening minor device N opens the file (if any) connected to file-descriptor
  296.  * N belonging to the calling process. Note that this driver consists of only
  297.  * the ``open()'' routine, because all subsequent references to this file will
  298.  * be direct to the other driver.
  299.  *
  300.  * NFS version by
  301.  * Arnold Robbins -- Emory University Computing Center -- Summer 87
  302.  */
  303.  
  304. /*
  305.  * $Log:    dev_fd.c,v $
  306.  * Revision 1.6  87/07/10  10:24:13  root
  307.  * Removed debugging printfs. ADR.
  308.  * 
  309.  * Revision 1.5  87/07/10  10:20:12  root
  310.  * Added ENXIO check to inode version. ADR.
  311.  * 
  312.  * Revision 1.4  87/07/05  14:19:41  root
  313.  * Added NOFILE/ENXIO check, some minor cleanup. ADR.
  314.  * 
  315.  * Revision 1.3  87/07/05  10:46:48  root
  316.  * Brought the comments into sync with reality. Bug fix to inode version. ADR.
  317.  * 
  318.  * Revision 1.2  87/07/03  16:53:46  root
  319.  * NFS version of the driver. Works just fine on a sun. ADR.
  320.  * 
  321.  * Revision 1.1  84/12/01  21:38:17  chris
  322.  * Initial revision
  323.  * 
  324.  */
  325.  
  326. #include "fd.h"
  327. #if NFD > 0
  328.  
  329. #include "../h/param.h"
  330. #ifdef NFS
  331. #include "../h/time.h"
  332. #include "../h/vnode.h"
  333. #else
  334. #include "../h/inode.h"
  335. #endif
  336. #include "../h/file.h"
  337. #include "../h/dir.h"
  338. #include "../h/user.h"
  339. #include "../h/errno.h"
  340.  
  341. /*
  342.  * THIS CODE NEEDS CLEANING AS SOON AS ASSIGNMENTS TO u.u_* GO AWAY
  343.  */
  344.  
  345. /*
  346.  * The NFS mods are so extensive that I have decided to provide two whole
  347.  * copies of the routine, one for NFS and one for regular BSD, instead
  348.  * of mixing them up with ifdefs. The non-NFS code is the original
  349.  * version from UMD.  A.D.R.
  350.  */
  351.  
  352. #ifdef NFS
  353. /*
  354.  * XXX
  355.  *
  356.  * WARNING!!!!! This piece of code requires that a patch be made
  357.  * to the stock NFS 3.2 code in specfs/spec_vnodeops.c$spec_open().
  358.  * The modification is to pass a pointer to the vnode for this file
  359.  * into this routine in the call to (*cdewsw[major(dev)])(), as a fourth
  360.  * argument.
  361.  *
  362.  * Why? you ask. When this device is opened, open() calls copen() which calls
  363.  * vn_open(). Now, the whole idea behind this "device" is to substitute an
  364.  * already open file for this one. The way to do this is to hand back up a vnode
  365.  * for said open file. The regular inode version of this code has it easy.
  366.  * The file structure for this device points at the device's inode. Chuck
  367.  * that inode and substitute the inode of the already open file. It is not
  368.  * so easy in the NFS case, because *the file structure does not yet
  369.  * point at a vnode*. That is only done in copen() after the vn_open()
  370.  * completes. Right now, we're still in the middle of the open. So we have
  371.  * no way of getting at the original vnode unless it is passed in to us.
  372.  * So that is why spec_open() has to pass a pointer to the vnode (pointer)
  373.  * to us, so we can switch it around.
  374.  */
  375.  
  376. fdopen (dev, mode, newdev, vpp)
  377. dev_t dev;
  378. int mode;
  379. dev_t *newdev;
  380. struct vnode **vpp;    /* vnode for this device */
  381. {
  382.     struct file *fp, *wfp;
  383.     struct vnode *vp, *wvp;
  384.     int vmode = 0;
  385.     int rwmode, error;
  386.  
  387.     if (minor(dev) >= NOFILE)    /* sanity check */
  388.         return (ENXIO);
  389.  
  390.     *newdev = dev;    /* XXX - force loop termination in spec_open() */
  391.  
  392.     /*
  393.      * Note the horrid kludge here: u.u_r.r_val1 contains the value
  394.      * of the new file descriptor, which has not been disturbed since
  395.      * it was allocated.
  396.      */
  397.  
  398.     if ((fp = getf(u.u_r.r_val1)) == NULL)
  399.         return (u.u_error);
  400.  
  401.     if ((wfp = getf(minor(dev))) == NULL)
  402.         return (u.u_error);
  403.  
  404.     /*
  405.      * We must explicitly test for this case because ufalloc() may
  406.      * have allocated us the same file desriptor we are referring
  407.      * to, if the proccess referred to an invalid (closed) descriptor.
  408.      * Ordinarily this would be caught by getf(), but by the time we
  409.      * reach this routine u_pofile[minor(dev)] could already be set
  410.      * to point to our file struct.
  411.      */
  412.     if (fp == wfp)
  413.         return (EBADF);
  414.  
  415.     vp = *vpp;
  416.  
  417.     /*
  418.      * Fake a ``dup()'' sys call if it isn't a vnode.
  419.      */
  420.     if (wfp->f_type != DTYPE_VNODE) {
  421.         /*
  422.          * Check that the mode the file is being opened
  423.          * for is consistent with the mode of the existing
  424.          * descriptor. This isn't as clean as it should be,
  425.          * but this entire driver is a real kludge anyway.
  426.          */
  427.         rwmode = mode & (FREAD|FWRITE);
  428.         if ((wfp->f_flag & rwmode) != rwmode)
  429.             return (EACCES);
  430.  
  431.         /* Delete references to this pseudo-device. */
  432.         VN_RELE(vp);        /* Chuck the vnode. */
  433.         fp->f_count = 0;    /* Chuck the file structure. */
  434.         crfree(fp->f_cred);
  435.         /* Dup the file descriptor. */
  436.         dupit(u.u_r.r_val1, wfp, u.u_pofile[minor(dev)]);
  437.         *vpp = (struct vnode *)wfp->f_data;    /* needed? */
  438.         return (0);
  439.     }
  440.  
  441.     /*
  442.      * now have a regular vnode.
  443.      */
  444.     error = 0;
  445.     wvp = (struct vnode *)wfp->f_data;
  446.  
  447.     /*
  448.      * Since we're opening a file again, we run through all the
  449.      * permission checks so this can't be used as a loophole to
  450.      * get access to a file we shouldn't have.  (GROT)
  451.      */
  452.     if (mode & FREAD && (error = VOP_ACCESS(wvp, VREAD, u.u_cred)))
  453.         goto bad;
  454.     if (mode & (FWRITE|FTRUNC)) {
  455.         if (vp->v_type == VDIR) {
  456.             error = EISDIR;
  457.             goto bad;
  458.         }
  459.         if ((error = VOP_ACCESS(wvp, VWRITE, u.u_cred)))
  460.             goto bad;
  461.     }
  462.  
  463.     /*
  464.      * The file must always exist, so we don't even bother testing
  465.      * for its presence.
  466.      */
  467.     if ((mode & (FCREAT|FEXCL)) == (FCREAT|FEXCL)) {
  468.         error = EEXIST;
  469.         goto bad;
  470.     }
  471.  
  472.     /*
  473.      * This may not make any sense, but I'm paranoid and figure that
  474.      * it's probably an error.
  475.      */
  476.     if (mode & FTRUNC) {
  477.         error = EBUSY;
  478.         goto bad;
  479.     }
  480.  
  481.     /* Call the device-specific open routine, if any. */
  482.     vmode = mode & ~(FCREAT | FEXCL);
  483.     if (wvp->v_type != VREG &&
  484.             (error = VOP_OPEN(&wvp, vmode, u.u_cred)) != 0)
  485.         goto bad;
  486.  
  487.     /*
  488.      * Made it this far, now return the other vnode back up the
  489.      * call chain for insertion into the file table entry.
  490.      */
  491.     VN_RELE(vp);        /* We don't need this anymore. */
  492.     wvp->v_count++;
  493.     *vpp = wvp;
  494.     return (0);
  495.  
  496. bad:
  497.     return (error);
  498. }
  499.  
  500. #else    /* ! NFS */
  501.  
  502. fdopen(dev, mode)
  503. dev_t dev;
  504. int mode;
  505. {
  506.     struct file *fp, *wfp;
  507.     struct inode *ip, *wip;
  508.     int rwmode, error;
  509.  
  510.     /* this check added by ADR */
  511.     if (minor(dev) >= NOFILE)    /* sanity check */
  512.         return (ENXIO);
  513.  
  514.     /*
  515.      * Note the horrid kludge here: u.u_r.r_val1 contains the value
  516.      * of the new file descriptor, which has not been disturbed since
  517.      * it was allocated.
  518.      */
  519.     if ((fp = getf(u.u_r.r_val1)) == NULL)
  520.         return (u.u_error);
  521.  
  522.     if ((wfp = getf(minor(dev))) == NULL)
  523.         return (u.u_error);
  524.  
  525.     /*
  526.      * We must explicitly test for this case because ufalloc() may
  527.      * have allocated us the same file desriptor we are referring
  528.      * to, if the proccess referred to an invalid (closed) descriptor.
  529.      * Ordinarily this would be caught by getf(), but by the time we
  530.      * reach this routine u_pofile[minor(dev)] could already be set
  531.      * to point to our file struct.
  532.      */
  533.     if (fp == wfp)
  534.         return (EBADF);
  535.  
  536.     ip = (struct inode *)fp->f_data;
  537.  
  538.     /*
  539.      * Fake a ``dup()'' sys call if it isn't an inode.
  540.      */
  541.     if (wfp->f_type != DTYPE_INODE) {
  542.         /*
  543.          * Check that the mode the file is being opened
  544.          * for is consistent with the mode of the existing
  545.          * descriptor. This isn't as clean as it should be,
  546.          * but this entire driver is a real kludge anyway.
  547.          */
  548.         rwmode = mode & (FREAD|FWRITE);
  549.         /* ADR: Bug fix: wfp below was originally fp */
  550.         if ((wfp->f_flag & rwmode) != rwmode)
  551.             return (EACCES);
  552.  
  553.         /* Delete references to this pseudo-device. */
  554.         irele(ip);        /* Chuck the inode. */
  555.         fp->f_count = 0;    /* Chuck the file structure. */
  556.         /* Dup the file descriptor. */
  557.         dupit(u.u_r.r_val1, wfp, u.u_pofile[minor(dev)]);
  558.         return (0);
  559.     }
  560.  
  561.     error = 0;
  562.     wip = (struct inode *)wfp->f_data;
  563.  
  564.     /*
  565.      * I'm not sure that we really need to lock the inode here,
  566.      * but why not be paranoid?
  567.      */
  568.     ilock(wip);
  569.  
  570.     /*
  571.      * Since we're opening a file again, we run through all the
  572.      * permission checks so this can't be used as a loophole to
  573.      * get access to a file we shouldn't have.  (GROT)
  574.      */
  575.     if (mode & FREAD && access(wip, IREAD))
  576.         goto bad;
  577.     if (mode & (FWRITE|FTRUNC)) {
  578.         if ((ip->i_mode&IFMT) == IFDIR) {
  579.             error = EISDIR;
  580.             goto bad;
  581.         }
  582.         if (access(wip, IWRITE))
  583.             goto bad;
  584.     }
  585.  
  586.     /*
  587.      * The file must always exist, so we don't even bother testing
  588.      * for its presence.
  589.      */
  590.     if ((mode & (FCREAT|FEXCL)) == (FCREAT|FEXCL)) {
  591.         error = EEXIST;
  592.         goto bad;
  593.     }
  594.  
  595.     /*
  596.      * This may not make any sense, but I'm paranoid and figure that
  597.      * it's probably an error.
  598.      */
  599.     if (mode & FTRUNC) {
  600.         error = EBUSY;
  601.         goto bad;
  602.     }
  603.  
  604.     /* Call the device-specific open routine, if any. */
  605.     if ((error = openi(wip, mode)) != 0)
  606.         goto bad;
  607.  
  608.     /*
  609.      * Made it this far, now switch the inode pointers in the
  610.      * file descriptors around, to make this file open refer
  611.      * to the other file.
  612.      */
  613.     irele(ip);        /* We don't need this anymore. */
  614.     fp->f_data = (caddr_t)wip;
  615.     wip->i_count++;
  616.     iunlock(wip);
  617.     return (0);
  618.  
  619. bad:
  620.     iunlock(wip);
  621.     return (error);
  622. }
  623.  
  624. #endif /* NFS */
  625. #endif /* NFD > 0 */
  626. SHAR_EOF
  627. chmod +x 'dev_fd.c'
  628. fi # end of overwriting check
  629. echo shar: extracting "'PATCH'" '(544 characters)'
  630. if test -f 'PATCH'
  631. then
  632.     echo shar: will not over-write existing file "'PATCH'"
  633. else
  634. cat << \SHAR_EOF > 'PATCH'
  635. *** /tmp/,RCSt1013388    Fri Jul 10 10:31:15 1987
  636. --- spec_vnodeops.c    Sun Jul  5 17:27:24 1987
  637. ***************
  638. *** 129,135 ****
  639.               if ((u_int)major(dev) >= nchrdev)
  640.                   return (ENXIO);
  641.   
  642. !             error = (*cdevsw[major(dev)].d_open)(dev,flag, &newdev);
  643.   
  644.               /*
  645.                * If this is an indirect device we need to do the
  646. --- 132,139 ----
  647.               if ((u_int)major(dev) >= nchrdev)
  648.                   return (ENXIO);
  649.   
  650. !             error = (*cdevsw[major(dev)].d_open)(dev,flag, &newdev,
  651. !                                     vpp);
  652.   
  653.               /*
  654.                * If this is an indirect device we need to do the
  655. SHAR_EOF
  656. chmod +x 'PATCH'
  657. fi # end of overwriting check
  658. #    End of shell archive
  659. exit 0
  660. -- 
  661. Arnold Robbins
  662. ARPA, CSNET:    arnold@emory.ARPA    BITNET: arnold@emory
  663. UUCP:    { decvax, gatech, sun!sunatl }!emory!arnold
  664. ONE-OF-THESE-DAYS:    arnold@emory.mathcs.emory.edu
  665.  
  666. -- 
  667.  
  668. Rich $alz            "Anger is an energy"
  669. Cronus Project, BBN Labs    rsalz@bbn.com
  670. Moderator, comp.sources.unix    sources@uunet.uu.net
  671.